package kr.co.redcircle.broker.io.net.Unicast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

import kr.co.redcircle.broker.Broker;
import kr.co.redcircle.broker.io.BrokerRequest;
import kr.co.redcircle.broker.io.IHandler;
import kr.co.redcircle.broker.registry.Registry;
import kr.co.redcircle.broker.security.KeyCollection;
import net.sf.json.JSONObject;

public class HostCallHandler implements Runnable {

	private JSONObject request = null;
	private boolean sFlag;

	public HostCallHandler(JSONObject requestString, boolean secureFlag) {
		this.request = requestString;
		this.sFlag = secureFlag;
	}

	@Override
	public void run() {
		
		if (this.request != null){
			synchronized (request) {

				Socket clientSocket;
				
				String hostString = this.request.getString(Broker.HOST);
				Integer portInt = (Integer) this.request.get(Broker.PORT);
				String requestString = request.toString();  
				
				try {
					
					System.out.println("host : " + hostString + "::" + portInt);
					if (this.sFlag){
						
						KeyCollection kCollection = Registry.getKeyCollection();
						SSLContext ctx = SSLContext.getInstance("TLS");
						ctx.init(kCollection.getKeyManagers(), kCollection.getTrustManagers(), null);
						
			            SSLSocketFactory sslsocketfactory = ctx.getSocketFactory();
			            clientSocket = sslsocketfactory.createSocket(hostString, portInt);
			            
					}else{
						
						clientSocket = new Socket(hostString, portInt);
					}
					PrintWriter requestWriter = new PrintWriter(clientSocket.getOutputStream(), true);
					BufferedReader requestReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
					String responseString = null;
					requestWriter.write(requestString + Broker.LINE_DIV);
					requestWriter.flush();
					
					System.out.println("requestWriter.flush()");
					responseString = requestReader.readLine();
					System.out.println("requestReader.readLine() :: " + responseString);
					
			    	IHandler respHandler = getResponseHandler(responseString);

			    	if (respHandler == null){
			    		BrokerRequest req = (BrokerRequest) JSONObject.toBean(JSONObject.fromObject(responseString), BrokerRequest.class);
			    		if (req != null) System.out.println("procResult : " + req.get(Broker.MENT));
			    	}else{
			    		respHandler.invoke(responseString);				    		
			    	}

			    	requestReader.close();
				    requestWriter.close();
				    clientSocket.close();		

				} catch (UnknownHostException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (NoSuchAlgorithmException e) {
					e.printStackTrace();
				} catch (KeyManagementException e) {
					e.printStackTrace();
				}
				
			}
		}		
	}

	private IHandler getResponseHandler(String responseString){
		
		IHandler retHandler = null;
		if (responseString != null && !responseString.toLowerCase().equals("null")){
			System.out.println("responseString : " + responseString);
			JSONObject respJSON = JSONObject.fromObject(responseString);
			String respId = null;
			
			String cid = Registry.getCID();
	
			if (cid == null) cid = "";
			System.out.println("CID : " + cid);
			
			boolean checkFlag = cid.equals(Broker.NAMENODE) || cid.startsWith(Broker.MONITOR_S) || cid.startsWith(Broker.WORKER);
			String requestMethodString = null;
			
			if (checkFlag){
				requestMethodString = respJSON.getString(Broker.TO) + "." + respJSON.getString(Broker.BUSINESS_S) + "." + respJSON.getString(Broker.METHOD);
			}else{
				requestMethodString = cid + "." + respJSON.getString(Broker.BUSINESS_S) + "." + respJSON.getString(Broker.METHOD);
			}
			
			if (requestMethodString.indexOf(Broker.NULL) > -1){
				return null;
			}else{
				System.out.println("HostCallHandler.getResponseHandler() ==> requestMethodString : " + requestMethodString);
				return Registry.getHandler(requestMethodString);
			}
		}
		return retHandler;
	}

}
